Neste laboratório, foram utilizadas as bibliotecas OpenCV2, Pywt e MatplotLib, dentro do ambiente de desenvolvimento do Google Colab, para desenvolvimento de atividades relativas à codificações de imagens com a Transformada DWT (Discrete Wavelet Transform), utilizando a linguagem Python.
Dentre as atividades de codificação desenvolvidas, foi possível atingir os seguintes objetivos:
Link para o ambiente Colab utilizado no desenvolvimento desta prática:
Abaixo, temos a importação das bibliotecas utilizadas ao longo do código utilizado nesta prática:
import numpy as np
import cv2 as cv
import pywt
import pywt.data
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import pandas as pd
import os
from IPython.display import HTML
Nesta primeira tarefa, foi realizada uma codificação DWT, com as imagens dos três integrantes do grupo, através da função Codificacao_DWT_PB() que recebe como parâmetro o caminho para cada uma das imagens.
A função funciona da seguinte forma:
pywt.dwt2, bem como sua inversa, por meio da função pywt.idwt2O código utilizado e o resultado obtido, podem ser vistos abaixo:
def Codificacao_DWT_PB(path):
img = mpimg.imread(path)
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
coefs2 = pywt.dwt2(img_gray,'haar', mode='periodization') #1 nível de DWT
(cA, (cH, cV, cD)) = coefs2 #Separando os coeficientes
imgr = pywt.idwt2(coefs2, 'haar', mode = 'periodization') #1 nível de IDWT
display(HTML("<h2> Plot dos Coeficientes da transformada DWT</h2>"))
plt.figure(figsize=(10,10))
plt.subplot(2,2,1)
plt.imshow(cA,'gray'); plt.title("CA - Aproximação")
plt.subplot(2,2,2)
plt.imshow(cV,'gray'); plt.title("CV - Bordas Verticais")
plt.subplot(2,2,3)
plt.imshow(cH,'gray'); plt.title("CH - Bordas Horizontais")
plt.subplot(2,2,4)
plt.imshow(cD,'gray'); plt.title("CD - Bordas Diagonais")
plt.show()
# Cálculo do Erro Quadrático Médio (MSE) e da Relação Sinal Ruído de Pico (PSNR)
# Calculo da MSE P&B
display(HTML("<h2>Comparativo Imagem Original(P&B) x Reconstruída DWT</h2>"))
A, L, Camadas = img.shape
dif = img_gray - imgr
MSE_gray = np.sum(np.matmul(dif,np.transpose(dif)))/(A*L)
PSNR_Y = 20*np.log10(255) - 10*np.log10(MSE_gray)
plt.figure(figsize=(20,10))
infograf = "Imagem Reconstruída de Luminância (Y) com PSNR = " + str(round(PSNR_Y,2)) + ' dB'
plt.subplot(1,2,1); plt.imshow(img_gray,'gray'); plt.title("Imagem Original P&B")
plt.subplot(1,2,2); plt.imshow(imgr,'gray'); plt.title(infograf)
plt.show()
print("MSE_Y = {:.2e}".format(MSE_gray))
print("PSNR_Luma = {:.2f} dB".format(PSNR_Y))
return MSE_gray,PSNR_Y
Abaixo, temos os resultados obtidos por cada um dos integrantes do Grupo:
MSE_1, PSNR_Y_1 = Codificacao_DWT_PB("/content/Bieljpg.jpg")
MSE_Y = 2.12e-24 PSNR_Luma = 284.86 dB
MSE_2, PSNR_Y_2 = Codificacao_DWT_PB("/content/Vitao.jpg");
MSE_Y = 9.58e-25 PSNR_Luma = 288.31 dB
MSE_3, PSNR_Y_3 = Codificacao_DWT_PB("/content/jow.jpg");
MSE_Y = 1.06e-24 PSNR_Luma = 287.89 dB
Podemos notar que as imagens reconstruídas dos três integrantes apresentam perda de qualidade pouco perceptível à olho nu, sendo capazes de serem percebidas igualmente, pela visão humana.
Contudo, analisando os erros, vemos que a imagem reconstruída do Integrante 2 (Victor), apresentou maior Relação sinal Ruído, com $PSNR = 288.31dB$.
A imagem do Integrante 1 (Gabriel), apresentou o menor PSNR ($PSNR=284dB$) dentre as três imagens, contudo apresentou o maior Erro quarático, da ordem de $2.12\cdot10^{-24}$.
Nesta parte, foram testadas as funções de DWT multiresolução, como a função pywt.wavedec2().
Basicamente, equanto a função utilizada na parte anterior pywt.dwt2(), aplica a DWT na imagem e fornece diretamente as matrizes dos coeficientes de aproximação e detalhe, em um único nível.
A função pywt.wavedec2(), fornece apenas o vetor de decomposição, que contém o número de coeficientes por nível, sendo possível obter múltiplas matrizes com os coeficientes de aproximação e de detalhe a partir do vetor de decomposição.
Nesta aplicação, através da função DWT_Multinivel_PB(), obtivemos uma aproximação para as imagens dos integrantes do grupo em tons de cinza, por meio de dois níveis diferentes, sendo que a partir do nível 2, obtemos os coefientes de aproximação e detalhe, enquanto o nível 1 é utilizado apenas para se obter os coeficientes de detalhe.
O código utilizado e o resultado obtido, podem ser vistos abaixo:
def DWT_Multinivel_PB(path):
img = mpimg.imread(path)
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
C = pywt.wavedec2(img_gray,'haar', mode = 'symmetric', level=2) # Dois níveis de decomposição DWT
imgr2 = pywt.waverec2(C, 'haar', mode = 'symmetric') # Dois níveis de IDWT
# Para extrair os coeficientes de cada nível
cA2 = C[0] # Coeficientes de Aproximação nível 2
(cH1, cV1, cD1) = C[-1] # Coeficientes de Detalhes nível 1
(cH2, cV2, cD2) = C[-2] # Coeficientes de Detalhes nível 2
# Imagem Original
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
display(HTML("<h2>Plot dos Coeficientes do Nível 2 - Wavedec2</h2>"))
# Plot dos coeficientes do nível 2
plt.figure(figsize=(7,7))
plt.subplot(2,2,1)
plt.imshow(cA2, 'gray'); plt.title('Ap. N2: CA2')
plt.subplot(2,2,2)
plt.imshow(cV2, 'gray'); plt.title('B. V. N2: CV2')
plt.subplot(2,2,3)
plt.imshow(cH2, 'gray'); plt.title('B. H. N2: CH2')
plt.subplot(2,2,4)
plt.imshow(cD2, 'gray'); plt.title('B. D. N2: CD2')
plt.show()
# Plot Original e Reconstrução
display(HTML("<h2>Plot Original (P&B) x Imagem Reconstruída - Wavedec2</h2>"))
plt.figure(figsize=(20,10))
plt.subplot(1,2,1); plt.imshow(img_gray,'gray'); plt.title('Imagem Original')
plt.subplot(1,2,2); plt.imshow(imgr2,'gray'); plt.title('Imagem Reconstruída')
plt.show()
#1 Nivel
CV1 = cV1.copy()
CH1 = cH1.copy()
CD1 = cD1.copy()
#2 Nivel
CA2 = cA2.copy()
CH2 = cH2.copy()
CV2 = cV2.copy()
CD2 = cD2.copy()
# Matriz Final Completa
CA1 = np.bmat([[CA2,CV2],[CH2,CD2]])
CC = np.bmat([[CA1,CV1],[CH1,CD1]])
plt.figure(figsize=(20,20))
plt.imshow(CC,'gray')
plt.title('Codificação de Imagem em multinível com função wavedec2()')
return CA2,imgr2
Abaixo, temos os resultados obtidos por cada um dos integrantes do Grupo:
cA2_Biel,imgr2_Biel = DWT_Multinivel_PB("/content/Bieljpg.jpg")
cA2_Victao,imgr2_Victao = DWT_Multinivel_PB("/content/Vitao.jpg");
cA2_Jow,imgr2_Jow = DWT_Multinivel_PB("/content/jow.jpg");
Podemos notar que o resultado da imagem reconstruída obtida através dos coeficientes presentes nos múltiplos níveis da função pywt.wavedec2(), traz um resultado visualmente muito próximo, nos três casos observados, relativamente ao resultado obtido pela função dwt2(), utilizada no item anterior.
Nesta terceira tarefa, foi realizada uma codificação DWT colorida, incluindo os três canais de cores da escala RGB, com as imagens dos três integrantes do grupo, através da função Codificacao_DWT_RGB().
A função funciona da seguinte forma:
O código utilizado e o resultado obtido, podem ser vistos abaixo:
def Codificacao_DWT_RGB(path,n1,cA2,imgr2):
# Imagem Original
img = mpimg.imread(path)
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
# Imagem Original
plt.figure(figsize=(10,10))
plt.imshow(img); plt.title("Imagem Original")
plt.show()
# Codificação por planos de cores
# Plano Vermelho
display(HTML("<h2>Reconstrução canal Vermelho</h2>"))
coefs_R = pywt.dwt2(img[:,:,0],'haar', mode='periodization') #1 nível de DWT R
(cA_R, (cH_R, cV_R, cD_R)) = coefs_R #Separando os coeficientes
cr_R = pywt.idwt2(coefs_R, 'haar', mode = 'periodization') #1 nível de IDWT R
plt.figure(figsize=(10,10))
plt.subplot(2,2,1)
plt.imshow(cA_R,'Reds_r'); plt.title("CA_Red - Aproximação")
plt.subplot(2,2,2)
plt.imshow(cV_R,'Reds_r'); plt.title("CV_Red - Bordas Verticais")
plt.subplot(2,2,3)
plt.imshow(cH_R,'Reds_r'); plt.title("CH_Red - Bordas Horizontais")
plt.subplot(2,2,4)
plt.imshow(cD_R,'Reds_r'); plt.title("CD_Red - Bordas Diagonais")
plt.figure(figsize=(10,10))
plt.imshow(cr_R, 'Reds_r'); plt.title("Imagem Reconstruída Red")
plt.show()
# Plano Verde
display(HTML("<h2>Reconstrução canal Verde</h2>"))
coefs_G = pywt.dwt2(img[:,:,1],'haar', mode='periodization') #1 nível de DWT G
(cA_G, (cH_G, cV_G, cD_G)) = coefs_G #Separando os coeficientes
cr_G = pywt.idwt2(coefs_G, 'haar', mode = 'periodization') #1 nível de IDWT G
plt.figure(figsize=(10,10))
plt.subplot(2,2,1)
plt.imshow(cA_G,'Greens_r'); plt.title("CA_Green - Aproximação")
plt.subplot(2,2,2)
plt.imshow(cV_G,'Greens_r'); plt.title("CV_Green - Bordas Verticais")
plt.subplot(2,2,3)
plt.imshow(cH_G,'Greens_r'); plt.title("CH_Green - Bordas Horizontais")
plt.subplot(2,2,4)
plt.imshow(cD_G,'Greens_r'); plt.title("CD_Green - Bordas Diagonais")
plt.figure(figsize=(10,10))
plt.imshow(cr_G, 'Greens_r'); plt.title("Imagem Reconstruída Green")
plt.show()
# Plano Azul
display(HTML("<h2>Reconstrução canal Azul</h2>"))
coefs_B = pywt.dwt2(img[:,:,2],'haar', mode='periodization') #1 nível de DWT B
(cA_B, (cH_B, cV_B, cD_B)) = coefs_B #Separando os coeficientes
cr_B = pywt.idwt2(coefs_B, 'haar', mode = 'periodization') #1 nível de IDWT B
plt.figure(figsize=(10,10))
plt.subplot(2,2,1)
plt.imshow(cA_B,'Blues_r'); plt.title("CA_Blue - Aproximação")
plt.subplot(2,2,2)
plt.imshow(cV_B,'Blues_r'); plt.title("CV_Blue - Bordas Verticais")
plt.subplot(2,2,3)
plt.imshow(cH_B,'Blues_r'); plt.title("CH_Blue - Bordas Horizontais")
plt.subplot(2,2,4)
plt.imshow(cD_B,'Blues_r'); plt.title("CD_Blue - Bordas Diagonais")
plt.figure(figsize=(10,10))
plt.imshow(cr_B, 'Blues_r'); plt.title("Imagem Reconstruída Blue")
plt.show()
# Reconstrução Nível 1 Colorida
display(HTML("<h2>Reconstrução Nível 1 - Todos os Canais (RGB)</h2>"))
A1, L1 = cA_R.shape
imgrec1 = np.zeros((A1,L1,3))
imgrec1[:,:,0] = cA_R.copy()
imgrec1[:,:,1] = cA_G.copy()
imgrec1[:,:,2] = cA_B.copy()
plt.figure(figsize=(10,10))
plt.imshow(imgrec1.astype(np.uint32)); plt.title("Imagem Reconstruída DWT/IDWT Nível 1")
plt.show()
# obtenha aproximação de NÍVEL 1 e converte para inteiro
C1 = pywt.wavedec2(img_gray,'haar', mode = 'symmetric', level=1) # Um nível de decomposição DWT
CA1_ = 255 * C1[0] / np.abs(C1[0]).max()
CA1_ = CA1_.astype(int)
# aproximação de NÍVEL 2 - ja´obtido no item (D) e converte para inteiro
CA2_ = 255 * cA2 / np.abs(cA2).max()
CA2_ = CA2_.astype(int)
# Salva no drive
cv.imwrite(n1+'_DWT_N1_Y.jpg', CA1_) # Aproximação Nível 1 só Y
cv.imwrite(n1+'_DWT_N2_Y.jpg', CA2_) # Aproximação Nível 2 só Y
# Aproximação Nível 1 Colorida
# converte RGB para BGR e converte para inteiro
imgrec1_ = np.zeros((A1,L1,3))
imgrec1_[:,:,0] = imgrec1[:,:,2]
imgrec1_[:,:,1] = imgrec1[:,:,1]
imgrec1_[:,:,2] = imgrec1[:,:,0]
imgrec1_ = ( 255 * imgrec1_ / np.abs(imgrec1_).max() ).astype(int)
# Salva no drive
#cv.imwrite(n1+'_DWT_N1_colorida.jpg', imgrec1_) # Gravando Aproximação Nível 1 Colorida
# Reconstrução Colorida Original
A,L = imgr2.shape
imgrec = np.zeros((A,L,3))
imgrec[:,:,0] = cr_R.copy()
imgrec[:,:,1] = cr_G.copy()
imgrec[:,:,2] = cr_B.copy()
# Calculo do MSE colorida
dif2 = img - imgrec
MSE_R = np.sum(np.matmul(dif2[:,:,0],np.transpose(dif2[:,:,0])))/(A*L) # Erro Quadrático Médio plano R
MSE_G = np.sum(np.matmul(dif2[:,:,1],np.transpose(dif2[:,:,1])))/(A*L) # Erro Quadrático Médio plano G
MSE_B = np.sum(np.matmul(dif2[:,:,2],np.transpose(dif2[:,:,2])))/(A*L) # Erro Quadrático Médio plano B
MSE_T = MSE_R + MSE_G + MSE_B
print("MSE_Red= {:.2e}".format(MSE_R), "\nMSE_Green= {:.2e}".format(MSE_G), "\nMSE_Blue= {:.2e}".format(MSE_B))
# Cálculo da SNR de pico colorida (PSNR), 3 camadas R, G e B
PSNR = 20*np.log10(255) - 10*np.log10(MSE_R + MSE_G + MSE_B)
print("PSNR total = {:.2f} dB".format(PSNR))
plt.figure(figsize=(10,10))
infograf2 = "Imagem Reconstruída com PSNR total = " + str(round(PSNR,2)) + ' dB'
plt.imshow(imgrec.astype(np.uint32)); plt.title(infograf2)
plt.show()
imgrec[:,:,0] = cr_B.copy()
imgrec[:,:,1] = cr_G.copy()
imgrec[:,:,2] = cr_R.copy()
imgrec = ( 255 * imgrec / np.abs(imgrec).max() ).astype(int)
cv.imwrite(n1+'_DWT_N1_colorida.jpg', imgrec)
return PSNR, MSE_T
PSNR = []
MSE = []
PSNR1, MSE1 = Codificacao_DWT_RGB("/content/Bieljpg.jpg","Biel",cA2_Biel,imgr2_Biel)
PSNR.append(PSNR1)
MSE.append(MSE1)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
MSE_Red= 2.18e-24 MSE_Green= 2.31e-24 MSE_Blue= 2.10e-24 PSNR total = 279.94 dB
PSNR2, MSE2 = Codificacao_DWT_RGB("/content/Vitao.jpg","Victao",cA2_Victao,imgr2_Victao)
PSNR.append(PSNR2)
MSE.append(MSE2)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
MSE_Red= 1.63e-24 MSE_Green= 7.85e-25 MSE_Blue= 6.72e-25 PSNR total = 283.23 dB
PSNR3, MSE3 = Codificacao_DWT_RGB("/content/jow.jpg","Jow",cA2_Jow,imgr2_Jow)
PSNR.append(PSNR3)
MSE.append(MSE3)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
MSE_Red= 1.21e-24 MSE_Green= 9.98e-25 MSE_Blue= 1.05e-24 PSNR total = 283.00 dB
Abaixo, temos a tabela comparativa, com o tamanho das imagens originais, o tamanho das imagens codificadas com a DWT, a relação sinal ruído de pico (PSNR), erro quadrático Médio (MSE) e a taxa de compressão alcançada com a codificação.
Analisando os dados, podemos ver que a PSNR é aproximadamente igual para as três imagens (entorno de 280dB) e que a imagem com a maior taxa de compressão foi a do Integrante 2, chegando a -60% do tamanho da imagem original, contudo, foi a imagem que também apresentou a maior relação PSNR (283.23dB).
#Obtem o Tamanho dos arquivos DWT e Originais
original = os.path.getsize("/content/Bieljpg.jpg"),os.path.getsize("/content/Vitao.jpg"),os.path.getsize("/content/jow.jpg")
DWT = os.path.getsize("/content/Biel_DWT_N1_colorida.jpg"),os.path.getsize("/content/Victao_DWT_N1_colorida.jpg"),os.path.getsize("/content/Jow_DWT_N1_colorida.jpg")
#Monta Tabela com os dados de interesse
df = pd.DataFrame(data=[original,DWT,PSNR,MSE]).T
df.columns=["Original(Bytes)","DWT(Bytes)","PSNR","MSE"]
df["Space Saving(%)"] = ((df["DWT(Bytes)"]/df["Original(Bytes)"])-1)*100
df["Compression Ratio(%)"] = (df["Original(Bytes)"]/df["DWT(Bytes)"])*100
df
| Original(Bytes) | DWT(Bytes) | PSNR | MSE | Space Saving(%) | Compression Ratio(%) | |
|---|---|---|---|---|---|---|
| 0 | 460363.0 | 216392.0 | 279.938705 | 6.594926e-24 | -52.995354 | 212.744926 |
| 1 | 464484.0 | 182282.0 | 283.231413 | 3.089862e-24 | -60.756022 | 254.816164 |
| 2 | 352922.0 | 169155.0 | 283.002087 | 3.257405e-24 | -52.070146 | 208.638231 |
Nesta quarta tarefa, foi utilizada a mesma função do item 3. com uma ligeira adaptação para substituir os canais de cores da escala RGB para a escala YCrCb.
Sendo assim, a estrutura da função foi preservada, bem como sua metodologia, sofrendo apenas pequenas adaptações para construção da função Codificacao_DWT_YCrCb().
O código utilizado e o resultado obtido, podem ser vistos abaixo:
def Codificacao_DWT_YCrCb(path,n1):
# Imagem Original
img = cv.imread(path)
img = cv.cvtColor(img, cv.COLOR_BGR2YCrCb)
y1, cr1, cb1 = cv.split(img)
C = pywt.wavedec2(y1,'haar', mode = 'symmetric', level=1) # Um nivel de decomposição DWT
imgr2 = pywt.waverec2(C, 'haar', mode = 'symmetric') # Um nivel nível IDWT
# Imagem Original
plt.figure(figsize=(20,20))
plt.imshow(img); plt.title("Imagem Original")
plt.show()
# Codificação por planos de cores
# Plano Y
display(HTML("<h2>Reconstrução canal Y</h2>"))
coefs_R = pywt.dwt2(y1,'haar', mode='periodization') #1 nível de DWT R
(cA_R, (cH_R, cV_R, cD_R)) = coefs_R #Separando os coeficientes
cr_R = pywt.idwt2(coefs_R, 'haar', mode = 'periodization') #1 nível de IDWT R
plt.figure(figsize=(20,20))
plt.subplot(2,2,1)
plt.imshow(cA_R, cmap='gray'); plt.title("CA_Y - Aproximação")
plt.subplot(2,2,2)
plt.imshow(cV_R, cmap='gray'); plt.title("CV_Y - Bordas Verticais")
plt.subplot(2,2,3)
plt.imshow(cH_R, cmap='gray'); plt.title("CH_Y - Bordas Horizontais")
plt.subplot(2,2,4)
plt.imshow(cD_R, cmap='gray'); plt.title("CD_Y - Bordas Diagonais")
plt.figure(figsize=(20,20))
plt.imshow(cr_R, cmap='gray'); plt.title("Imagem Reconstruída Y")
plt.show()
# Plano CR
display(HTML("<h2>Reconstrução canal CR</h2>"))
coefs_G = pywt.dwt2(cr1,'haar', mode='periodization') #1 nível de DWT G
(cA_G, (cH_G, cV_G, cD_G)) = coefs_G #Separando os coeficientes
cr_G = pywt.idwt2(coefs_G, 'haar', mode = 'periodization') #1 nível de IDWT G
plt.figure(figsize=(20,20))
plt.subplot(2,2,1)
plt.imshow(cA_G); plt.title("CA_Cr - Aproximação")
plt.subplot(2,2,2)
plt.imshow(cV_G); plt.title("CV_Cr - Bordas Verticais")
plt.subplot(2,2,3)
plt.imshow(cH_G); plt.title("CH_Cr - Bordas Horizontais")
plt.subplot(2,2,4)
plt.imshow(cD_G); plt.title("CD_Cr - Bordas Diagonais")
plt.figure(figsize=(20,20))
plt.imshow(cr_G); plt.title("Imagem Reconstruída Cr")
plt.show()
# Plano CB
display(HTML("<h2>Reconstrução canal Cb</h2>"))
coefs_B = pywt.dwt2(cb1,'haar', mode='periodization') #1 nível de DWT B
(cA_B, (cH_B, cV_B, cD_B)) = coefs_B #Separando os coeficientes
cr_B = pywt.idwt2(coefs_B, 'haar', mode = 'periodization') #1 nível de IDWT B
plt.figure(figsize=(20,20))
plt.subplot(2,2,1)
plt.imshow(cA_B); plt.title("CA_Cb - Aproximação")
plt.subplot(2,2,2)
plt.imshow(cV_B); plt.title("CV_Cb - Bordas Verticais")
plt.subplot(2,2,3)
plt.imshow(cH_B); plt.title("CH_Cb - Bordas Horizontais")
plt.subplot(2,2,4)
plt.imshow(cD_B); plt.title("CD_Cb - Bordas Diagonais")
plt.figure(figsize=(20,20))
plt.imshow(cr_B); plt.title("Imagem Reconstruída Cb")
plt.show()
# Reconstrução Nível 1 Colorida
display(HTML("<h2>Reconstrução Nível 1 - Todos os Canais (YCrCb)</h2>"))
A1, L1 = cA_R.shape
imgrec1 = np.zeros((A1,L1,3))
imgrec1[:,:,0] = cA_R.copy()
imgrec1[:,:,1] = cA_G.copy()
imgrec1[:,:,2] = cA_B.copy()
plt.figure(figsize=(10,10))
plt.imshow(imgrec1.astype(np.uint32)); plt.title("Imagem Reconstruída DWT/IDWT Nível 1")
plt.show()
# Aproximação Nível 1 Colorida YCrCb
imgrec1_ = np.zeros((A1,L1,3))
imgrec1_[:,:,0] = imgrec1[:,:,0]
imgrec1_[:,:,1] = imgrec1[:,:,1]
imgrec1_[:,:,2] = imgrec1[:,:,2]
imgrec1_ = ( 255 * imgrec1_ / np.abs(imgrec1_).max() ).astype(int)
# Reconstrução Colorida Original
A, L = imgr2.shape
imgrec = np.zeros((A,L,3))
imgrec[:,:,0] = cr_R.copy()
imgrec[:,:,1] = cr_G.copy()
imgrec[:,:,2] = cr_B.copy()
# Calculo do MSE colorida
dif2 = img - imgrec
MSE_R = np.sum(np.matmul(dif2[:,:,0],np.transpose(dif2[:,:,0])))/(A*L) # Erro Quadrático Médio plano R
MSE_G = np.sum(np.matmul(dif2[:,:,1],np.transpose(dif2[:,:,1])))/(A*L) # Erro Quadrático Médio plano G
MSE_B = np.sum(np.matmul(dif2[:,:,2],np.transpose(dif2[:,:,2])))/(A*L) # Erro Quadrático Médio plano B
MSE_T = MSE_R + MSE_G + MSE_B
print("MSE_Y= {:.2e}".format(MSE_R), "\nMSE_Cr= {:.2e}".format(MSE_G), "\nMSE_Cb= {:.2e}".format(MSE_B))
# Cálculo da SNR de pico colorida (PSNR), 3 camadas Y, Cr e Cb
PSNR = 20*np.log10(255) - 10*np.log10(MSE_R + MSE_G + MSE_B)
print("PSNR total = {:.2f} dB".format(PSNR))
plt.figure(figsize=(20,20))
infograf2 = "Imagem Reconstruída com PSNR total = " + str(round(PSNR,2)) + ' dB'
plt.imshow(imgrec.astype(np.uint32)); plt.title(infograf2)
plt.show()
# Salva no drive
cv.imwrite(n1+'_DWT_N1_colorida.jpg', imgrec) # Gravando Aproximação Nível 1 Colorida
return PSNR, MSE_T
PSNR4, MSE4 = Codificacao_DWT_YCrCb("/content/foto_grupo.jpg","Grupo")
PSNR.append(PSNR4)
MSE.append(MSE4)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
MSE_Y= 1.16e-24 MSE_Cr= 1.41e-24 MSE_Cb= 1.13e-24 PSNR total = 282.44 dB
Abaixo, temos a tabela comparativa, com o tamanho das imagens originais, o tamanho das imagens codificadas com a DWT, a relação sinal ruído de pico (PSNR), erro quadrático Médio (MSE) e a taxa de compressão alcançada com a codificação.
Nesta Tabela, temos o comparativo com os dados das imagens dos três integrantes separados, codificada através da DWT com escala RGB, bem como a imagem de montagem com os três integrantes do grupo, codificada através da DWT com escala YCrCb.
#Obtem o Tamanho dos arquivos DWT e Originais
original = os.path.getsize("/content/Bieljpg.jpg"),os.path.getsize("/content/Vitao.jpg"),os.path.getsize("/content/jow.jpg"),os.path.getsize("/content/foto_grupo.jpg")
DWT = os.path.getsize("/content/Biel_DWT_N1_colorida.jpg"),os.path.getsize("/content/Victao_DWT_N1_colorida.jpg"),os.path.getsize("/content/Jow_DWT_N1_colorida.jpg"),os.path.getsize("/content/Grupo_DWT_N1_colorida.jpg")
#Monta Tabela com os dados de interesse
df = pd.DataFrame(data=[original,DWT,PSNR,MSE]).T
df.columns=["Original(Bytes)","DWT(Bytes)","PSNR(dB)","MSE"]
df["Space Saving(%)"] = ((df["DWT(Bytes)"]/df["Original(Bytes)"])-1)*100
df["Compression Ratio(%)"] = (df["Original(Bytes)"]/df["DWT(Bytes)"])*100
df["Imagens"] = ["Integrante 1","Integrante 2","Integrante 3","Montagem Grupo"]
df
| Original(Bytes) | DWT(Bytes) | PSNR(dB) | MSE | Space Saving(%) | Compression Ratio(%) | Imagens | |
|---|---|---|---|---|---|---|---|
| 0 | 460363.0 | 216392.0 | 279.938705 | 6.594926e-24 | -52.995354 | 212.744926 | Integrante 1 |
| 1 | 464484.0 | 182282.0 | 283.231413 | 3.089862e-24 | -60.756022 | 254.816164 | Integrante 2 |
| 2 | 352922.0 | 169155.0 | 283.002087 | 3.257405e-24 | -52.070146 | 208.638231 | Integrante 3 |
| 3 | 1178324.0 | 255346.0 | 282.441507 | 3.706207e-24 | -78.329729 | 461.461703 | Montagem Grupo |
Analisando os dados, podemos observar que a imagem de montagem com os três integrantes do grupo, sofre a maior compressão, chegando à -78.32% do tamanho da imagem original.
Esta diferença pode ser explicada por ser a única imagem dentre as 4, codificada com DWT em escala de cores YCrCb, equanto as demais foram codificadas em RGB.
Visando dar sequência ao estudo de codificação de imagens, neste laboratório foi possível aplicar a técnica de compressão da transformada de wavelet, uma variante da codificação de transformada discreta de cosseno (DCT) que usa wavelets em vez do algoritmo baseado em bloco do DCT.
Para aplicar o método, foi necessário explorar algumas técnicas de pré-processamento nas imagens, tendo em vista a conversão e adaptação do esquema de cores dos canais RGB para outras escalas e aplicação da transformada nos layers padronizados.
Assim como na transformada discreta de cosseno, como parte do experimento, foi possível analisar a qualidade das imagens reconstruídas qualitativa e quantitativamente, através da Relação sinal Ruído e da Relação Sinal Ruído de Pico, o que demonstrou uma grande competência por parte dos algoritmos em trabalhar com a manipulação da distribuição dos dados durante as transformações sem que houvessem perdas significativas.
Desse modo, bem como fora discorrido, foi possível denotar a capacidade de preservação das estruturas funcionais, bem como metodológicas do processo de codificação através da DWT, sofrendo apenas pequenas adaptações para construção da função e êxito em realizar a compressão das imagens, com resultados de maior compressão equivalentes à -78.32% do original quando utilizada a compressão em escala de cores YCrCb.
HTML(f'<audio controls><source src="https://github.com/gabrielsouza-oss/CSM/blob/main/labs/audio_desc_lab4.mp3?raw=true" type="audio/ogg"></audio>')